<script>
import '../assets/styles/mindmap.css';
import Instructions from './Instructions.vue';
import ZoomControl from './ZoomControl.vue';
export default {
  name: 'MindMap',
  components: { Instructions, ZoomControl },
  data() {
    return {
      // 画布状态
      scale: 1,
      translateX: 0,
      translateY: 0,
      isSpaceDown: false,
      isLeftMouseDown: false,
      dragStartX: 0,
      dragStartY: 0,
      isDragging: false,
      // 节点数据结构
      nodes: [
        { id: 1, text: '中心主题', x: 400, y: 300, type: 'root' },
        { id: 2, text: '子主题 1', x: 600, y: 200, type: 'child' },
        { id: 3, text: '子主题 2', x: 600, y: 400, type: 'child' }
      ],

      // 连线数据
      connections: [
        { from: 1, to: 2 },
        { from: 1, to: 3 }
      ],

      // 当前选中的节点
      selectedNode: null,
      // 第二个选中的节点（用于重新连接）
      secondSelectedNode: null,

      // 当前正在编辑的节点
      editingNode: null,

      // 编辑文本
      editText: '',

      // 拖拽状态
      dragState: {
        isDragging: false,
        startX: 0,
        startY: 0,
        nodeId: null,
      }
    }


  },
  mounted() {
    window.addEventListener('mousemove', this.onDrag);
    window.addEventListener('mouseup', this.endDrag);
    document.addEventListener('keydown', this.handleKeyDown);
    document.addEventListener('keyup', this.handleKeyUp);
  },

  beforeDestroy() {
    document.removeEventListener('keydown', this.handleKeyDown);
    document.removeEventListener('keyup', this.handleKeyUp);
  },
  methods: {
    // 清除选中状态
    clearSelection(event) {
      // 如果点击的是节点或工具栏，不清除选中状态
      if (event.target.closest('.node') || event.target.closest('.toolbar')) return;

      this.selectedNode = null;
      this.secondSelectedNode = null;
    },
    // 选择节点
    selectNode(node, event) {
      // 如果是拖拽结束，不触发选中状态的切换
      if (this.dragState.isDragging) return;

      event.stopPropagation(); // 阻止事件冒泡到容器

      // 如果按住Ctrl键
      if (event.ctrlKey) {
        // 如果已经选中了两个节点，不允许再选
        if (this.selectedNode && this.secondSelectedNode) return;

        // 如果点击的是已选中的节点，取消选中
        if (this.selectedNode && this.selectedNode.id === node.id) {
          this.selectedNode = null;
          return;
        }
        if (this.secondSelectedNode && this.secondSelectedNode.id === node.id) {
          this.secondSelectedNode = null;
          return;
        }

        // 设置第一个或第二个选中节点
        if (!this.selectedNode) {
          this.selectedNode = node;
        } else if (!this.secondSelectedNode) {
          this.secondSelectedNode = node;
        }
      } else {
        // 没有按Ctrl键，普通点击
        // 如果点击的是当前选中的节点，取消选中
        if (this.selectedNode && this.selectedNode.id === node.id) {
          this.selectedNode = null;
          this.secondSelectedNode = null;
          return;
        }

        // 更新选中状态为新节点
        this.selectedNode = node;
        this.secondSelectedNode = null;
      }
    },
    // 检查节点是否为孤岛
    isOrphanNode(nodeId) {
      return !this.connections.some(conn => conn.from === nodeId || conn.to === nodeId);
    },

    // 创建新连接
    createConnection() {
      if (!this.selectedNode || !this.secondSelectedNode) return;

      // 检查是否至少有一个是孤岛节点
      if (!this.isOrphanNode(this.selectedNode.id) && !this.isOrphanNode(this.secondSelectedNode.id)) {
        return;
      }

      this.connections.push({
        from: this.selectedNode.id,
        to: this.secondSelectedNode.id
      });

      // 重置选择状态
      this.secondSelectedNode = null;
    },

    // 删除节点
    deleteNode() {
      if (!this.selectedNode || this.selectedNode.type === 'root') return;

      const nodeId = this.selectedNode.id;

      // 删除所有相关连线
      for (let i = this.connections.length - 1; i >= 0; i--) {
        if (this.connections[i].from === nodeId || this.connections[i].to === nodeId) {
          this.connections.splice(i, 1);
        }
      }

      // 删除节点
      const nodeIndex = this.nodes.findIndex(n => n.id === nodeId);
      if (nodeIndex !== -1) {
        this.nodes.splice(nodeIndex, 1);
      }

      this.selectedNode = null;
      this.secondSelectedNode = null;
    },

    // 开始拖拽节点
    startDrag(event, node) {
      event.preventDefault();
      this.dragState.isDragging = true;
      this.dragState.startX = event.clientX;
      this.dragState.startY = event.clientY;
      this.dragState.nodeId = node.id;
      this.selectNode(node);
    },

    // 拖拽移动
    onDrag(event) {
      if (!this.dragState.isDragging) return;

      const dx = event.clientX - this.dragState.startX;
      const dy = event.clientY - this.dragState.startY;

      const node = this.nodes.find(n => n.id === this.dragState.nodeId);
      if (node) {
        node.x += dx;
        node.y += dy;
      }

      this.dragState.startX = event.clientX;
      this.dragState.startY = event.clientY;
    },

    // 结束拖拽
    endDrag() {
      this.dragState.isDragging = false;
    },

    // 处理鼠标滚轮事件
    handleWheel(e) {
      e.preventDefault();

      const rect = e.currentTarget.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;

      // 计算鼠标在内容中的相对位置（考虑平移但不考虑缩放）
      const mouseXInContent = mouseX - this.translateX;
      const mouseYInContent = mouseY - this.translateY;

      const delta = e.deltaY > 0 ? -0.05 : 0.05;
      const newScale = Math.max(0.1, Math.min(2, this.scale + delta));

      // 更新缩放比例，但不改变平移值
      this.scale = newScale;
    },

    // 放大
    zoomIn() {
      const newScale = Math.min(2, this.scale + 0.1);
      // 只更新缩放比例，不改变平移值
      this.scale = newScale;
    },

    // 缩小
    zoomOut() {
      const newScale = Math.max(0.1, this.scale - 0.1);
      // 只更新缩放比例，不改变平移值
      this.scale = newScale;
    },

    // 重置缩放
    resetZoom() {
      this.scale = 1;
      this.translateX = 0;
      this.translateY = 0;
    },

    // 处理鼠标按下事件
    handleMouseDown(e) {
      if (this.isSpaceDown && e.button === 0) {
        this.isLeftMouseDown = true;
        this.dragStartX = e.clientX;
        this.dragStartY = e.clientY;
        this.isDragging = false;

        document.body.style.cursor = 'grabbing';
        e.preventDefault();
      }
    },

    // 处理鼠标移动事件
    handleMouseMove(e) {
      if (this.isSpaceDown && this.isLeftMouseDown) {
        this.isDragging = true;

        const deltaX = e.clientX - this.dragStartX;
        const deltaY = e.clientY - this.dragStartY;

        this.translateX += deltaX;
        this.translateY += deltaY;

        this.dragStartX = e.clientX;
        this.dragStartY = e.clientY;
      }
    },

    // 处理鼠标抬起事件
    handleMouseUp(e) {
      if (e.button === 0 && this.isLeftMouseDown) {
        this.isLeftMouseDown = false;
        this.isDragging = false;

        document.body.style.cursor = this.isSpaceDown ? 'grab' : 'default';
      }
    },

    // 处理键盘按下事件
    handleKeyDown(e) {
      if (e.key === ' ' && !this.isSpaceDown) {
        this.isSpaceDown = true;
        document.body.style.cursor = this.isLeftMouseDown ? 'grabbing' : 'grab';
      } else if (e.key === 'Delete' && this.selectedNode && this.selectedNode.type !== 'root') {
        this.deleteNode();
      } else if (e.key === 'Escape' && this.editingNode) {
        this.editingNode = null;
      }
      // 注意：Enter键的处理逻辑已移至handleKeyUp函数
    },

    // 处理键盘抬起事件
    handleKeyUp(e) {
      if (e.key === ' ') {
        this.isSpaceDown = false;
        document.body.style.cursor = 'default';

        if (this.isLeftMouseDown) {
          this.isLeftMouseDown = false;
          this.isDragging = false;
        }
      } else if (e.key === 'Enter' && this.selectedNode) {
        // 在Enter键松开时调用addNode()函数，确保新节点保持编辑状态
        this.addNode();
      }
    },

    // 添加新节点
    addNode() {
      if (!this.selectedNode) return;

      const newId = Math.max(...this.nodes.map(n => n.id)) + 1;
      const offsetX = 200;
      const offsetY = 0;

      const newNode = {
        id: newId,
        text: '新主题',
        x: this.selectedNode.x + offsetX,
        y: this.selectedNode.y + offsetY,
        type: 'child'
      };

      this.nodes.push(newNode);
      this.connections.push({ from: this.selectedNode.id, to: newId });

      // 立即进入编辑模式
      this.editNode(newNode);

      return newNode;
    },

    // 编辑节点文本
    editNode(node) {
      this.editingNode = node;
      this.editText = node.text;

      // 在下一个事件循环中聚焦输入框
      setTimeout(() => {
        const input = document.getElementById('node-edit-input');
        if (input) input.focus();
      }, 0);
    },

    // 保存编辑
    saveEdit() {
      if (this.editingNode) {
        this.editingNode.text = this.editText;
        this.editingNode = null;
      }
    },

    // 计算连线路径
    getConnectionPath(from, to) {
      const fromNode = this.nodes.find(n => n.id === from);
      const toNode = this.nodes.find(n => n.id === to);

      if (!fromNode || !toNode) return '';

      return `M ${fromNode.x} ${fromNode.y} C ${fromNode.x + 100} ${fromNode.y}, ${toNode.x - 100} ${toNode.y}, ${toNode.x} ${toNode.y}`;
    },
  },
  computed: {
    canvasStyle() {
      return {
        transform: `translate(${this.translateX}px, ${this.translateY}px)`,
        transformOrigin: '0 0'
      };
    },
    contentStyle() {
      return {
        transform: `scale(${this.scale})`,
        transformOrigin: '0 0'
      };
    }
  },
}

</script>

<template>
  <div class="mind-map-container" @wheel="handleWheel" @mousemove="handleMouseMove" @mouseup="handleMouseUp"
    @mousedown="handleMouseDown" @click="clearSelection" :style="{ cursor: isSpaceDown ? 'grab' : 'default' }">
    <div class="toolbar">
      <button @click="addNode" :disabled="!selectedNode">添加节点</button>
      <button @click="deleteNode" :disabled="!selectedNode || selectedNode.type === 'root'">删除节点</button>
      <button @click="createConnection"
        :disabled="!selectedNode || !secondSelectedNode || (!isOrphanNode(selectedNode.id) && !isOrphanNode(secondSelectedNode.id))">连接节点</button>
    </div>

    <div class="canvas" :style="canvasStyle">
      <!-- 连线 -->
      <svg class="connections">
        <path v-for="conn in connections" :key="`${conn.from}-${conn.to}`" :d="getConnectionPath(conn.from, conn.to)"
          class="connection-path" :style="contentStyle" />
      </svg>

      <!-- 内容容器 - 应用缩放 -->
      <div class="content" :style="contentStyle">
        <!-- 节点 -->
        <div v-for="node in nodes" :key="node.id" class="node" :class="{
          'node-root': node.type === 'root',
          'node-child': node.type === 'child',
          'node-selected': selectedNode && selectedNode.id === node.id,
          'node-second-selected': secondSelectedNode && secondSelectedNode.id === node.id,
          'node-orphan': isOrphanNode(node.id)
        }" :style="{ left: `${node.x}px`, top: `${node.y}px` }" @mousedown="startDrag($event, node)"
          @click.stop="selectNode(node, $event)" @dblclick="editNode(node)">
          <template v-if="editingNode && editingNode.id === node.id">
            <input id="node-edit-input" v-model="editText" @blur="saveEdit" @keyup.enter="saveEdit"
              @keyup.esc="editingNode = null" />
          </template>
          <template v-else>
            {{ node.text }}
          </template>
        </div>
      </div>
    </div>

    <Instructions />
    <ZoomControl :scale="scale" @zoom-in="zoomIn" @zoom-out="zoomOut" @reset-zoom="resetZoom" />
  </div>
</template>

<style>
.node-second-selected {
  border-color: #4CAF50 !important;
  box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
}

.node-orphan {
  border-style: dashed !important;
}
</style>